home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / Book Chapters / 02 - Basic Game Graphics / Palette Anim ƒ / Palette Anim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-30  |  10.4 KB  |  338 lines  |  [TEXT/MMCC]

  1. //\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
  2. //
  3. //    Palette Anim.c
  4. //
  5. //    Simple demonstration of Palette Animation. This method of animation is extremely useful
  6. //    in a very narrow range of applications--certainly worthy of experimenting with and keeping
  7. //    in mind as a solution.
  8. //
  9. //    The cpu load of Palette animation is low, and you may notice that your cursor does not
  10. //    flicker when placed over animating objects. These are both side-effects of the fact that
  11. //    all we're really doing is moving around a very few bytes in the Palette to acheive these
  12. //    effects. Palette animation is a keen trick, and sometimes *just* what the doctor ordered.
  13. //
  14. //    History:
  15. //
  16. //    950301 jb: Written
  17. //
  18. //\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
  19.  
  20.  
  21. //  __#Defines________________________________________________________________________
  22. #define kMainWindowResID        1000
  23. #define kAppColorTableResID        1024
  24.  
  25. #define kColorBoxCIndex        2                        //palette entry number for our color box
  26. #define kColorBoxC2Index    3                        //palette entry number for color box border
  27. #define    kColorBoxLeft        10
  28. #define    kColorBoxTop        10
  29. #define    kColorBoxWidth        220
  30. #define    kColorBoxHeight        ((kColorBoxWidth / 5) * 3)    //3x5 is nice ratio
  31.  
  32. #define kFlickerBoxCIndex    4                        //palette entry we'll use for this box
  33. #define    kFlickerBoxLeft        kColorBoxLeft + 8
  34. #define    kFlickerBoxTop        kColorBoxTop + 8
  35. #define    kFlickerBoxWidth    32
  36. #define    kFlickerBoxHeight    kFlickerBoxWidth
  37.  
  38. #define    kChaserCIndexOffset    6                        //1st chaser color at entry kChaserCIndexOffset,
  39. #define    kNumChasers            24                        //defines how many chasers we'll draw
  40. #define    kChaserRadius        48                        //max radius of chaser circle
  41. #define    kChaserDotSize        8                        //how big chaser should be
  42.                                                     //last at kChaserCIndexOffset + kNumChasers - 1
  43.  
  44. #define kBackgroundIndex    200                        //index of background color
  45.  
  46. #define    kDrawPaletteEntriesAtTop    FALSE            //draws all 256 entries in small rectangle
  47.                                                     //this feature is more for debugging than
  48.                                                     //demonstration, but is included as an
  49.                                                     //instructive aid.
  50.  
  51. //  __#Headers________________________________________________________________________
  52. #include <Palettes.h>
  53. #include <math.h>        //for transcendental functions
  54. #include "Utils.h"
  55.  
  56. //  __#Protos_________________________________________________________________________
  57. //  __ Macros_________________________________________________________________________
  58. //  __ Enums__________________________________________________________________________
  59. //  __ Typedefs_______________________________________________________________________
  60. //  __ Static Protos__________________________________________________________________
  61. static Boolean OpenMainWindow( void );
  62. static void DoDemo( void );
  63. static void Render( void );
  64. static void AnimateFrame( void );
  65.  
  66. //  __ Extern Globals_________________________________________________________________
  67.  
  68. //  __ Static Globals_________________________________________________________________
  69. static OSErr                gErr;
  70. static Str32                gAppName;
  71. static WindowPtr            gMainWindow;
  72. static CTabHandle            gOurColorTable;
  73. static PaletteHandle         gAppPalette;
  74. //  __ Functions______________________________________________________________________
  75.  
  76.  
  77. //____ main __________________________________________________________________________
  78. //
  79. void main( void )
  80. {
  81.     ToolBoxInit();
  82.     
  83.     if (!EnviroCheck())
  84.         ExitToShell();
  85.     
  86.     GetAppName((char *)gAppName);
  87.  
  88.     if (!OpenMainWindow())
  89.         ExitToShell();
  90.         
  91.     DoDemo();
  92.     
  93.     if(NULL != gMainWindow)
  94.         DisposeWindow(gMainWindow);
  95.     if(NULL != gOurColorTable)
  96.         DisposeCTable(gOurColorTable);
  97. }//main
  98.  
  99.  
  100. //____ OpenMainWindow __________________________________________________________________________
  101. //
  102. //    Open our window, install palette from a resource CTable.
  103. //
  104. static Boolean OpenMainWindow( void )
  105. {
  106.     // create and show the window, make sure it's frontmost
  107.     gMainWindow = GetNewCWindow( kMainWindowResID, ( Ptr )NULL, ( WindowPtr ) -1 );    
  108.     if (NULL == gMainWindow)            //real apps should handle this gracefully
  109.         return FALSE;
  110.     SetWTitle(gMainWindow,gAppName);
  111.  
  112.     //FYI: Animating offscreen palettes:
  113.     //Setting bit 14 of an offscreen's color table gives us a way to refer to palette 
  114.     //indexes instead of RGB values. The value[x] fields of the color table describe 
  115.     //which palette entry to use when drawing pixels with index x. This makes it 
  116.     //possible to use animated colors in an offscreen world. See "Palette Manager Animation,"
  117.     //by Rich Collyer in the Winter, 1991 issue of "develop" from Apple.
  118.     //    (**gOurColorTable).ctFlags |= 0x4000; //see Inside Mac VI pp 20-14
  119.  
  120.     //load in the color table, translate to palette, install in window
  121.     gOurColorTable = GetCTable( kAppColorTableResID );
  122.     if (NULL == gOurColorTable)
  123.         return FALSE;
  124.  
  125.     gAppPalette = NewPalette( 256, gOurColorTable, pmExplicit + pmTolerant, 0x0000 );
  126.         
  127.     NSetPalette( gMainWindow, gAppPalette, pmAllUpdates );
  128.     
  129.     ActivatePalette(gMainWindow);
  130.         
  131.     ShowWindow( gMainWindow );
  132.     SetPort( gMainWindow );
  133.  
  134.     //give us a nice, neutral background
  135.     PmForeColor(kBackgroundIndex);
  136.     PaintRect(&qd.thePort->portRect);
  137.  
  138.     return TRUE;
  139. }//OpenMainWindow
  140.  
  141.  
  142.  
  143.  
  144. //____ DoDemo __________________________________________________________________________
  145. //
  146. //    Nifty function shows off some ways to do Palette Animation
  147. //
  148. //    Returns    void
  149. //
  150. static void DoDemo( void )
  151. {
  152. Boolean            done;
  153. EventRecord        theEvent;
  154.  
  155.     done = FALSE;
  156.     while (!done)
  157.     {
  158.         if(WaitNextEvent(everyEvent, &theEvent, 0L, 0L))
  159.         {
  160.             switch (theEvent.what)
  161.             {
  162.                 case mouseDown:
  163.                 case keyDown:
  164.                     done = TRUE;
  165.                 case updateEvt:
  166.                     if ((WindowPtr) theEvent.message == gMainWindow)
  167.                     {
  168.                         BeginUpdate(gMainWindow);
  169.                         Render();
  170.                         AnimateFrame();
  171.                         EndUpdate(gMainWindow);
  172.                     }
  173.                 break;
  174.             }//switch (theEvent.what)
  175.         }//if WaitNextEvent
  176.  
  177.         AnimateFrame();
  178.  
  179.     }//while
  180.  
  181. }//DoDemo
  182.  
  183.  
  184. //____ Render __________________________________________________________________________
  185. //
  186. //    Draw objects using PmForeColor.
  187. //
  188. static void Render( void )
  189. {
  190. #define    kDrawText            TRUE                    //draws nicely-colored text in background
  191.  
  192. #define    mThetaStepSize         (6.283 / kNumChasers)    //how far around our circle to go
  193. #define    kChaserHalfDotSize    kChaserDotSize / 2        //make it easy to center chaser on point
  194.  
  195. short        step;
  196. short        x, y, cenX, cenY;
  197. double        theta;
  198. Rect        aRect;
  199.  
  200. #if kDrawText
  201. Handle        txtHdl;
  202. long        len;
  203. short        fontNum;
  204. #endif
  205.  
  206.     //Make our special colors animated
  207.     for (x = 2; x <= kBackgroundIndex; x++)
  208.     {
  209.         SetEntryUsage(gAppPalette, x, pmAnimated + pmExplicit, 0x0000);
  210.     }
  211.     for (x = kBackgroundIndex + 1; x < 256; x++)    //be nice to environment
  212.     {
  213.         SetEntryUsage(gAppPalette, x, pmTolerant, 0x7000);
  214.     }
  215.  
  216. #if kDrawText
  217.     //draw our text; note that it doesn't animate, even
  218.     //though it's drawn with the same index as the color
  219.     //box's frame, which *does* animate.
  220.     txtHdl = GetResource('TEXT', 128);
  221.     if (NULL != txtHdl)
  222.     {
  223.         len = GetHandleSize(txtHdl);
  224.         HLock(txtHdl);
  225.         GetFNum("\ppalatino",&fontNum);    //if palatino not found, fontNum == 0 == System font
  226.         TextFont(fontNum);
  227.         TextSize(12);
  228.  
  229.         //draw our text 
  230.         PmForeColor(kColorBoxC2Index);
  231.         PmBackColor(kBackgroundIndex);
  232.         aRect = gMainWindow->portRect;
  233.         aRect.right += 10000;    //avoid wrapping
  234.         TextBox(*txtHdl, len, &aRect, teJustLeft);
  235.         
  236.         ReleaseResource(txtHdl);
  237.     }
  238. #endif //kDrawText
  239.  
  240.  
  241. #if kDrawPaletteEntriesAtTop
  242.     //draw all palette entries at top
  243.     for (x = 0; x < 256; x++)
  244.     {
  245.         PmForeColor(x);
  246.         MoveTo(x, 0);
  247.         Line(0, 4);
  248.     }
  249. #endif
  250.  
  251.     //draw colorBox
  252.     SetRect(&aRect,    kColorBoxLeft, kColorBoxTop,
  253.                     kColorBoxLeft+kColorBoxWidth, kColorBoxTop+kColorBoxHeight);
  254.  
  255.     PmForeColor(kColorBoxC2Index);    //draw border
  256.     PaintRect(&aRect);
  257.     InsetRect(&aRect, 2, 2);
  258.     PmForeColor(kColorBoxCIndex);
  259.     PaintRect(&aRect);
  260.  
  261.     //draw flicker box
  262.     SetRect(&aRect, kFlickerBoxLeft, kFlickerBoxTop,
  263.                     kFlickerBoxLeft + kFlickerBoxWidth, kFlickerBoxTop + kFlickerBoxHeight);
  264.     PmForeColor(kFlickerBoxCIndex);
  265.     PaintRect(&aRect);
  266.     PmForeColor(251);
  267.     FrameRect(&aRect);
  268.  
  269.     //center our chasers on lower right corner of colorBox
  270.     cenX = kColorBoxLeft+kColorBoxWidth;
  271.     cenY = kColorBoxTop+kColorBoxHeight;
  272.  
  273.     //draw circle of chasers
  274.     for (step = 0, theta = 0.0; step < kNumChasers; step++)
  275.     {
  276.         theta += mThetaStepSize;
  277.         x = cenX + kChaserRadius * cos(theta);
  278.         y = cenY - kChaserRadius * sin(theta);
  279.  
  280.         PmForeColor(kChaserCIndexOffset + step);
  281.         SetRect(&aRect, x - kChaserHalfDotSize, y - kChaserHalfDotSize, x + kChaserHalfDotSize, y + kChaserHalfDotSize);
  282.         PaintOval(&aRect);
  283.     }
  284.     
  285.     //we've changed our palette, make sure the hardware knows about it!
  286.     ActivatePalette(gMainWindow);
  287.  
  288. }//Render
  289.  
  290.  
  291. //____ AnimateFrame __________________________________________________________________________
  292. //
  293. //    Called at regular intervals, this function manipulates pmAnimated colors in the
  294. //    Palette to create various sorts of color-cycling animaiton.
  295. //
  296. static void AnimateFrame( void )
  297. {
  298. #define kNumHSVSteps        200                        //used to create new colors to
  299. #define    mHSVThetaStep        (65535 / kNumHSVSteps)    //pop into Palette
  300.  
  301. static HSVColor        boxHSV = {0, 65535, 65535};
  302. static HSVColor        frameHSV = {32767, 65535, 65535};
  303. static double        hsvTheta;
  304. static Boolean        flickWhite = FALSE;
  305. static RGBColor        whiteRGB = {65535, 65535, 65535};
  306. static RGBColor        blackRGB = {0, 0, 0};
  307. RGBColor            tempRGB;
  308.  
  309.     //change color of our color box
  310.     boxHSV.hue += mHSVThetaStep;        //move clockwise along color wheel for next color
  311.     HSV2RGB(&boxHSV,&tempRGB);            //translate to RGB
  312.     AnimateEntry(gMainWindow, kColorBoxCIndex, &tempRGB);        //replace old color with new one
  313.  
  314.     //change color of our color box's border
  315.     frameHSV.hue += mHSVThetaStep;
  316.     HSV2RGB(&frameHSV,&tempRGB);
  317.     AnimateEntry(gMainWindow, kColorBoxC2Index, &tempRGB);
  318.  
  319.     //draw annoying, flickering box
  320.     flickWhite = !flickWhite;
  321.     if (flickWhite)
  322.         AnimateEntry(gMainWindow, kFlickerBoxCIndex, &whiteRGB);
  323.     else
  324.         AnimateEntry(gMainWindow, kFlickerBoxCIndex, &blackRGB);
  325.     
  326.     
  327.  
  328.     //here, we'll cause cycling by shifting our array of colors over 1, making sure
  329.     //that the color in 1st bucket gets stuck on the other end.
  330.     GetEntryColor(gAppPalette, kChaserCIndexOffset, &tempRGB);        //get 1st color
  331.     AnimatePalette(gMainWindow, gOurColorTable,                        //bump colors down 1
  332.         kChaserCIndexOffset + 1, kChaserCIndexOffset, kNumChasers);
  333.     AnimateEntry(gMainWindow, kChaserCIndexOffset + kNumChasers, &tempRGB);    //pop saved color
  334.                                                                             //onto end of array
  335.     Palette2CTab(gAppPalette, gOurColorTable);                        //grab color table, now
  336.                                                                     //that it's been modified
  337.  
  338. }//AnimateFrame